package net.inteidee.handler;


import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.persistence.EntityManager;
import javax.persistence.FlushModeType;

import javax.persistence.Query;
import javax.persistence.criteria.CriteriaQuery;

public abstract class GenericDAO<T> {

	EntityManager em = JPAUtil.getEntityManagerFActory().createEntityManager();

 private Class<T> entityClass;

	 public GenericDAO(Class<T> entityClass) {
	  this.entityClass = entityClass;
	 }

 public void save(T entity) {

	 
	 if(!em.isOpen())
		 em = JPAUtil.getEntityManagerFActory().createEntityManager();
	
	 try{
		 em.setFlushMode(FlushModeType.AUTO); //Il flush avviene in automatico non appena viene eseguita una operazione del database
		 em.getTransaction().begin();
		 em.persist(entity);
		 em.getTransaction().commit();	
	 }
	 catch (Exception e) {
		 em.getTransaction().rollback();
		 e.printStackTrace();
	}finally{
		em.close();
		
	}
 }

 
 public void delete(T entity) {
	 
	 if(!em.isOpen())
		 em = JPAUtil.getEntityManagerFActory().createEntityManager();
	
	 try{
		 em.setFlushMode(FlushModeType.AUTO);
		 em.getTransaction().begin();
		 T entityToBeRemoved = em.merge(entity);//l'oggetto detached diventa managed
		  em.remove(entityToBeRemoved);
		 em.getTransaction().commit();	
	 }
	 catch (Exception e) {
		 e.printStackTrace();

		 em.getTransaction().rollback();
	}finally{
		em.close();	}  
 }

 public void update(T entity) {
	 
	 if(!em.isOpen())
		 em = JPAUtil.getEntityManagerFActory().createEntityManager();
	
	 try{
		 em.setFlushMode(FlushModeType.AUTO);
		 em.getTransaction().begin();
		 em.merge(entity);
		 em.getTransaction().commit();	
	 }
	 catch (Exception e) {
		 em.getTransaction().rollback();
	}finally{
		em.close();	}
 }

 public T find(long entityID) {
	 
	 if(!em.isOpen())
		 em = JPAUtil.getEntityManagerFActory().createEntityManager();
	 
	 T object = em.find(entityClass, entityID);
	 em.close();
	 
	 return object;
 }
 
  //TODO anche qui deve essere aperta una Sessione JPA
	public List<T> findAll() {
		
		 if(!em.isOpen())
			 em = JPAUtil.getEntityManagerFActory().createEntityManager();
		
		 List<T> list = null;
		 
		 	try {
				list = em.createQuery("from "+entityClass.getName()).getResultList();

			} catch (Exception e) {
				// TODO: handle exception
				e.printStackTrace();
			}
			em.close();
			
			return list;
		
		
	}

	public T findOneResult(String hqlQuery, Map<String, Object> parameters) {
		T result = null;

		 if(!em.isOpen())
			 em = JPAUtil.getEntityManagerFActory().createEntityManager();
		
		try {
			Query query = em.createQuery(hqlQuery);

			// Method that will populate parameters if they are passed not null and empty
			if (parameters != null && !parameters.isEmpty()) {
				populateQueryParameters(query, parameters);
			}

			result = (T) query.getSingleResult();

		} catch (Exception e) {
			System.out.println("Error while running query: " + e.getMessage());
			e.printStackTrace();
		}

		return result;
	}

	private void populateQueryParameters(Query query, Map<String, Object> parameters) {

		for (Entry<String, Object> entry : parameters.entrySet()) {
			query.setParameter(entry.getKey(), entry.getValue());
		}
	}
}